#include "USART2_Config.h"

/**
    ******************************************************************************
    * 函数名称：USART2_Config
    * 功能描述：配置USART2串口通信参数
    * 输入参数：baud - 波特率（如9600,115200等）
    * 返回值  ：无
    * 详细说明：
    * 1. 使用PA2(TX)和PA3(RX)
    * 2. 通信格式同USART2
    * 3. 中断优先级低于USART2（1）
    * 典型应用：
    * - 连接蓝牙模块
    * - 与其他设备通信
    * 调用示例：
    *   USART2_Config(9600); // 配置为9600波特率
    ******************************************************************************
**/
void USART2_Config(u32 baud)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;

    /* 开启USART2和GPIOA时钟（USART2在APB1总线） */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* 配置PA2(TX)为复用推挽输出 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 配置PA3(RX)为浮空输入 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 配置USART2参数 */
    USART_InitStructure.USART_BaudRate = baud;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(USART2, &USART_InitStructure);

    /* 配置NVIC中断 */
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 次高优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* 使能接收中断 */
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

    /* 使能USART2 */
    USART_Cmd(USART2, ENABLE);
}

/**
    ******************************************************************************
    * 函数名称：USART2_IRQHandler
    * 功能描述：USART2中断服务函数（自动调用）
    * 输入参数：无
    * 返回值  ：无
    * 详细说明：
    * 1. 处理接收中断（USART_IT_RXNE）
    * 2. 接收数据后：
    *    - 控制PB5 LED闪烁（低电平点亮）
    *    - 将数据转发到USART2
    * 典型应用：
    * - 蓝牙模块数据透传
    * - 双串口数据桥接
    ******************************************************************************
**/
/*
void USART2_IRQHandler(void)
{
    u8 data;
    if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  // 检查接收中断标志
    {
        data = USART_ReceiveData(USART2);  // 读取接收数据
        USART_SendData(USART1, data);      // 数据转发到USART1
    }
}
*/

/**
    ******************************************************************************
    * 函数名称：USART2_SendByte
    * 功能描述：USART2发送单个字节（阻塞式）
    * 输入参数：Byte - 要发送的字节（0x00-0xFF）
    * 返回值  ：无
    * 详细说明：
    * 1. 直接写入DR寄存器启动发送
    * 2. 等待发送缓冲区空标志（TXE）
    * 3. 最大阻塞时间：1个字节传输时间（如115200波特率约87us）
    * 调用示例：
    *   USART2_SendByte(0x41); // 发送字符'A'
    ******************************************************************************
**/
void USART2_SendByte(u8 Byte)
{
    USART_SendData(USART2, Byte);  // 写入数据寄存器启动发送
    while(!USART_GetFlagStatus(USART2, USART_FLAG_TXE)); // 等待发送完成
}

/**
    ******************************************************************************
    * 函数名称：USART2_SendArray
    * 功能描述：发送字节数组
    * 输入参数：
    *   Array - 数组首地址指针
    *   Length - 数组长度（元素个数）
    * 返回值  ：无
    * 详细说明：
    * 1. 循环调用USART2_SendByte发送每个元素
    * 2. 适用于发送二进制数据块
    * 调用示例：
    *   u8 data[] = {0x01,0x02,0x03};
    *   USART2_SendArray(data, 3); // 发送3字节数据
    ******************************************************************************
**/
void USART2_SendArray(u8 *Array, u16 Length)
{
    u16 i;
    for(i = 0; i < Length; i++){
        USART2_SendByte(Array[i]);  // 逐个发送数组元素
    }
}

/**
    ******************************************************************************
    * 函数名称：USART2_SendString
    * 功能描述：发送字符串（以'\0'结尾）
    * 输入参数：String - 字符串指针
    * 返回值  ：无
    * 详细说明：
    * 1. 自动检测字符串结束符'\0'
    * 2. 支持标准C字符串格式
    * 调用示例：
    *   USART2_SendString("Hello World!"); // 发送字符串
    ******************************************************************************
**/
void USART2_SendString(char *String)
{
    u8 i;
    for(i = 0; String[i] != '\0'; i++){
        USART2_SendByte(String[i]);  // 逐个发送字符
    }
}

/**
    ******************************************************************************
    * 函数名称：USART2_Pow
    * 功能描述：计算x的y次方（用于数字分解）
    * 输入参数：
    *   x - 底数
    *   y - 指数
    * 返回值  ：计算结果（x^y）
    * 调用示例：
    *   USART2_Pow(10,2); // 返回100
    ******************************************************************************
**/
u32 USART2_Pow(u32 x, u32 y)
{
    uint32_t Result = 1;
    while(y--)
    {
        Result *= x;  // 累乘计算幂
    }
    return Result;
}


/**
    ******************************************************************************
    * 函数名称：USART2_SendNumber
    * 功能描述：发送固定位数的数字
    * 输入参数：
    *   Num - 要发送的数字（0-99999999）
    *   Length - 显示位数（1-8）
    * 返回值  ：无
    * 详细说明：
    * 1. 从高位到低位依次分解数字
    * 2. 不足位数前面补零
    * 3. 自动转换为ASCII字符
    * 调用示例：
    *   USART2_SendNumber(123,5); // 输出"00123"
    ******************************************************************************
**/
void USART2_SendNumber(u32 Num, u8 Length)
{
    u8 i;
    for(i = 0; i < Length; i++){
        // 分解各位数字并转换为ASCII
        USART2_SendByte((Num / USART2_Pow(10, Length - i - 1) % 10) + '0');
    }
}


/**
    ******************************************************************************
    * 函数名称：fputc2
    * 功能描述：重定向printf输出到串口2（MicroLIB专用）
    * 输入参数：
    *   ch - 要输出的字符
    *   f - 文件指针（未使用）
    * 返回值  ：输出的字符
    * 详细说明：
    * 1. 需在工程设置中启用MicroLIB
    * 2. 支持标准printf所有格式化功能
    * 3. 缓冲区有限，长字符串可能被截断
    ******************************************************************************
**/
int fputc2(int ch, FILE *f)
{
    USART2_SendByte(ch);  // 发送字符到串口1
    return ch;
}


/**
    ******************************************************************************
    * 函数名称：USART2_Printf
    * 功能描述：自定义格式化输出函数（不依赖MicroLIB）
    * 输入参数：
    *   format - 格式化字符串
    *   ... - 可变参数列表
    * 返回值  ：无
    * 详细说明：
    * 1. 使用vsprintf实现格式化
    * 2. 最大支持100字节缓冲区
    * 3. 自动添加字符串结束符
    * 调用示例：
    *   USART2_Printf("Temp=%.1fC",25.5); // 输出"Temp=25.5C"
    ******************************************************************************
**/
void USART2_Printf(char *format, ...)
{
    char String[100];      // 格式化缓冲区
    va_list arg;           // 可变参数指针
    
    va_start(arg, format); // 初始化可变参数
    vsprintf(String, format, arg); // 格式化字符串
    va_end(arg);           // 结束可变参数
    
    USART2_SendString(String); // 发送格式化后的字符串
}
